/**
 * websocket 对象
 */
class WebsocketUtils {
    socket: WebSocket | null
    init: Map<any, string> | null  = new Map()
    // 定时器重试次数， 链接超时轮询次数
    private reconnectCount: number = 50
    private roundTimeout: number = 5
    private roundTimeoutDefault: number = 5
    private roundTime : number = 6000
    private reconnectConutDefault: number = 50
    public baseUrl = (window.location.protocol == 'http:' ? 'ws://' : 'wss://') + window.location.host;
    // 定时器id
    interval?: any | null = null
    // 重连机制回调
    reconnectCB: any | null
    // 是否开启调试
    public debug: boolean = false
    // 是否重连标志
    private isReconnect: boolean = false
    //  websocket 回调函数
    private mseeageCB: any | null = null
    private openCB: any | null = null
    private closeCB: any | null = null
    private errorCB: any | null = null

    constructor(path: string = ''){
        this.baseUrl += path;
        this.socket = new WebSocket(this.baseUrl);
        this.interval = setInterval(()=>{
             // 链接超时
             if(this.socket?.readyState == WebSocket.CONNECTING) {
                if(this.roundTimeout >= 0 ){
                    this.roundTimeout--;
                    if(this.debug){
                        console.log('链接等待中，等待轮询次数'+this.roundTimeout);
                    }
                    return;
                }else{
                    if(this.debug){
                        console.log('链接超时...');
                    }
                    this.socket.close();
                    this.socket = null;
                    this.roundTimeout = this.roundTimeoutDefault;
                }
            }
            // 超时重链
            if( this.socket == null || this.socket.readyState == WebSocket.CLOSED || this.socket.readyState == WebSocket.CLOSING){
                this.socket == null;
                this.socket = new WebSocket(this.baseUrl);
                this.isReconnect = true;
                this.reconnectLisent();
                if(this.debug){
                    console.log('已经发起尝试重连');
                }
            }else{
                if(this.isReconnect){
                    if(this.socket.readyState == WebSocket.OPEN && this.isReconnect ){
                        this.reconnectInit();
                    }
                }
            }
            if(this.socket.readyState != WebSocket.OPEN && this.reconnectCount < 0){
                if(this.debug){
                    console.log("重连超过最大次数，重连机制已经关闭!");
                }
                this.close()
            }
            this.reconnectCount--;
        }, this.roundTime);
        this.socket.onerror=()=>{
            this.socket?.close();
        }
    }

    private reconnectLisent(){
        if(this.socket != null){
            if(this.mseeageCB != null){
                this.socket.onmessage = this.mseeageCB;
            }
            if(this.openCB != null){
                this.socket.onopen = this.openCB;
            }
            if(this.closeCB != null){
                this.socket.onclose = this.closeCB;
            }
            if(this.errorCB != null){
                this.socket.onerror = this.errorCB;
            } 
        }
    }

    private reconnectInit(){
        this.isReconnect = false;
        if(this.debug){
            console.log('已经重新链接成功');
        }
        if(this.reconnectCB != null){
            this.reconnectCB(this);
        }
        this.reconnectCount = this.reconnectConutDefault;
        this.roundTimeout = this.roundTimeoutDefault;
        this.init?.forEach((k, v) => {
            this.socket?.send(k);
        });
    }

    // 重连回调
    reconnect(count: number){
        this.reconnectCount = count;
        this.reconnectConutDefault = count;
    }

    // 轮询时间
    setRoundTime(roundTime: number){
        this.roundTime = roundTime;
        this.roundTimeoutDefault = roundTime;
    }

    // 轮询超时次数
    setRoundTimeout(roundTimeout: number){
        this.roundTimeout = roundTimeout;
    }

    setReconnectNumber(count: number){
        this.reconnectCount = count;
    }

    send(data: string){
        if(this.socket != null && this.socket.readyState == WebSocket.OPEN){
            this.socket.send(data);
        }else{
            if(this.debug){
                console.log('socket 未链接');
            }
        }
    }
    
    onerror(cb: any){
        this.errorCB = cb;
        if(this.socket != null){
            this.socket.onerror = cb;
        }
    }

    onclose(cb: any){
        this.closeCB = cb;
        if(this.socket != null){
            this.socket.onclose = cb;
        }
    }

    onmessage(cb: any){
        this.mseeageCB = cb;
        if(this.socket != null){
            this.socket.onmessage = cb;
        }
    }

    onopen(cb: any){
        this.openCB = cb;
        if(this.socket != null){
            this.socket.onopen = cb;
        }
    }
    
    addRecionnectSendMessage(k: string, v: string){
        this.init?.set(k, v);
    }

    deleteReconnectionSendMessage(k: string){
        this.init?.delete(k);
    }

    close(){
        clearInterval(this.interval);
        this.socket?.close();
        this.socket = null;
        this.closeCB = null;
        this.openCB = null;
        this.mseeageCB = null;
        this.errorCB = null;
        this.init?.clear()
        this.init = null;
    }
}

export { WebsocketUtils }